import csv

from django.shortcuts import render, redirect
from django.http.response import HttpResponse
from django.views.generic import ListView, View

from index.models import Product
# from index.form import ProductForm, ProductModelForm

# Create your views here.


# def index(request):
#     return HttpResponse('Hello World')


def mydate(request, year, month, day):
    return HttpResponse(str(year)+'/'+str(month)+'/'+str(day))


def mynewdate(request, year, month, day):
    return HttpResponse(str(year)+'/'+str(month)+'/'+str(day))


def gettext(request, text):
    return HttpResponse(str(text))


def myyear(request, year):
    return render(request, 'myyear.html',{
        'year': year
    })


def download(request):   # 返回下载内容
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment;filename="somethingfilename.csv"'
    writer = csv.writer(response)
    writer.writerow(['First row', 'A',  'B',  'C'])
    return response


def hello(request):  # 返回html页面，但是这种方法不是很友好
    return HttpResponse('<html><body><p style="color: red;">你好，这是欢迎页面</p></body></html>')


# def index(request):
#     type_list = Product.objects.values('type').distinct()
#     name_list = Product.objects.values("name", "type")
#     context = {
#         'title': '首页',
#         'type_list': type_list,
#         'name_list': name_list,
#     }
#
#     return render(request, "index.html", context=context, status=200)


# def index(request):
#     # 获取当前请求的用户名
#     username = request.user.username
#     return render(request, 'index.html', context=locals())


# 建议使用这种方式
# def index(request):
#     type_list = Product.objects.values('type').distinct()
#     name_list = Product.objects.values("name", "type")
#     title = '首页'
#     # 这里的locals()函数默认使用上面的type_list,name_list和title作为键值对，因此后面不可以随意命名
#     return render(request, "index.html", context=locals(), status=200)


# 演示重定向
# def login(request):
#     # 相对路径，代表首页地址
#     return redirect('/')

#
# def login(request):
#     if request.method == 'POST':
#         name = request.POST.get("name", '')
#         return redirect('/')
#     else:
#         if request.GET.get('name', ''):
#             name =request.GET.get('name', '')
#         else:
#             name = 'Everyone'
#         return HttpResponse('username is '+name)
#
#
# def test(request):
#     title = '首页'
#     return render(request, 'moban.html', context=locals())

# 基于类的视图，CBV模式
# class ProductList(ListView):
#     # context_object_name设置HTML模板的变量名称
#     context_object_name = 'type_list'
#     # template_name设定HTML模板
#     template_name = 'index_view.html'
#     # 查询数据，并且去重
#     queryset = Product.objects.values('type').distinct()
#
#     # 重写get_queryset方法，对模型product进行数据筛选
#     # def get_queryset(self):
#     #     type_list = Product.objects.values("type").distinct()
#     #     return type_list
#
#     # 添加其他变量
#     def get_context_data(self, *, object_list=None, **kwargs):
#         context =super().get_context_data(**kwargs)
#         context['name_list'] = Product.objects.values('name', 'type')
#         return context


# class ProductList(ListView):
#     def get_queryset(self):
#         # 获取url变量的id
#         print(self.kwargs['id'])
#         # 获取url的参数name
#         print(self.kwargs['name'])
#         # 获取请求方式
#         print(self.request.method)
#
#         type_list = Product.objects.values('type').distinct()
#         return type_list


# def index(request):
#     if request.method =='GET':
#         product_form = ProductForm()
#         return render(request, 'data_form.html', context=locals())
#     else:
#         product_form = ProductForm(request.POST)
#         if product_form.is_valid():
#             # 获取控件name的数据
#             # 方法1，直接可以得到name属性的值
#             # name = request.POST.get('name','')
#
#             # 方法2，这种形式获取的是form这个形成的表单，并不是直接name属性
#             # name = product_from['name']   # 这种形式获取的是form这个形成的表单
#
#             # 方法3，cleaned_data将控件name进行清洗，转换成Python数据类型
#             name = product_form.cleaned_data['name']
#             print(product_form)
#             print(name)
#             return HttpResponse('提交成功!')
#         else:
#             error_msg = product_form.errors.as_json()
#             print(error_msg)
#             return render(request, 'data_form.html', context=locals())


 # 基于函数的视图FBV
# def model_index(request, id):
#     if request.method == 'GET':
#         instance = Product.objects.filter(id=id)  # 前面的id是数据库中product的id，而后面的id则是传入的id
#         # 判断数据是否存在
#         if instance:
#             # 数据存在，则开始进行表单的实例化，并将查询结果进行显示
#             product_form = ProductModelForm(instance=instance[0])
#         else:
#             product_form = ProductModelForm()
#         return render(request, 'data_form.html', context=locals())
#     else:
#         product_form = ProductModelForm(request.POST)
#         if product_form.is_valid():
#             # 取出经过clean_data清洗过的weight，并转换为Python数据类型
#             weight = product_form.cleaned_data['weight']
#             # 数据保存方法1
#             # 直接将数据保存到数据库
#             # product_form.save()
#
#             # 数据保存方法2
#             # save方法设置commit=False，将生产数据库对象product_form_db，然后对该对象的属性值进行修改并保存
#             product_form_db = product_form.save(commit=False)
#             product_form_db.name = '我的iphone'
#             product_form_db.save()
#
#             # 数据保存方法3
#             # save_m2m方法用于保存ManyToMany的数据模型
#             # product_form_db.save_m2m()
#             return HttpResponse('提交成功！weight清洗后的数据为：'+weight)
#         else:
#             # 将错误信息输出，error_msg是将错误信息以json格式进行输出
#             error_msg = product_form.errors.as_json()
#             print(error_msg)
#             return render(request, 'data_form.html', context=locals())


# 基于类的视图CBV
# class ModelIndexView(View):
#     def get(self,request,id):
#         instance = Product.objects.filter(id =id)
#         if instance:
#             product_form = ProductModelForm(instance=instance[0])
#         else:
#             product_form = ProductModelForm()
#         return render(request, 'data_form.html', context=locals())
#
#     def post(self,request,id):
#         product_form = ProductModelForm(request.POST)
#         if product_form.is_valid():
#             weight = product_form.cleaned_data['weight']
#             print(weight)
#             product_form_db = product_form.save(commit=False)
#             product_form_db.name = '小米10'
#             product_form_db.save()
#             return HttpResponse('提交成功！weight清洗后的数据为：'+weight)
#         else:
#             error_msg = product_form.errors.as_json()
#             print(error_msg)
#             return render(request, 'data_form.html', context=locals())




# 仅仅用于设置网页的访问权限
# 使用login_required和permission_required分别对用户登录验证和用户权限验证
# login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None)
# redirect_field_name默认值是next，当登录成功之后，程序会自动跳回到之前浏览的页面
# login_url,设置登录页面的Url地址，默认是settings.py中设置的LOGIN_URL，而LOGIN_URL需要开发者自行在settings.py中配置


# permission_required(perm, login_url=None, raise_exception=False)
# permission_required，验证当前用户是否拥有相应的权限。若用户没有使用权限，程序会跳转到登录页面或者抛出异常。
# perm，必须参数，判断用户是否拥有权限。参数为固定格式，如index.Visit_Product，index为项目的APP名，Visit_Product是来自数据表auth_permission的字段codename。
# login_url,设置登录页面的Url地址,默认为None。若不设置参数，验证失败后会抛出404异常。
# raise_exception，设置抛出异常，默认值为False

# from django.contrib.auth.decorators import login_required, permission_required
#
# @login_required(login_url='/user/login')
# @permission_required(perm='index.Visit_Product', login_url='user/login')
# def index(request):
#     return render(request, 'index_auth_test.html', context=locals())


# permission_required的作用与内置函数has_perm相同，因此可以进行替换
# @login_required(login_url='user/login')
# def index(request):
#     user = request.user
#     if user.has_perm('index.Visit_Product'):
#         return render(request, 'index_auth_test.html', context=locals())
#     else:
#         return redirect('/user/login')



# 此处仅仅演示session机制时使用，用户必须登录后才能查阅，而且会使用到一些权限
# from django.contrib.auth.decorators import login_required, permission_required
#
# # 视图函数index
# # 使用login_required和permission_required分别对用户登录和用户权限进行验证
# @login_required(login_url='/user/login')
# @permission_required(perm='index.Visit_Product', login_url='/user/login')
# def index(request):
#     # 获取get请求参数,因为此处并没有表单提交（登录操作不是此视图完成的）
#     product = request.GET.get('product', '')
#     price = request.GET.get('price', '')
#     if product:
#         # 获取存储在session中的数据，若session中不存在product_info，则返回一个空列表
#         product_list = request.session.get('product_info', [])
#         # 判断当前请求是否已经存储在Session之中
#         if not product in product_list:
#             # 请求不在session之中，则进行添加
#             product_list.append({'price': price, 'product': product})
#         # 更新存储在Session中的数据
#         request.session['product_info'] = product_list
#         return redirect('/')
#     return render(request, 'index.html', context=locals())


# # 视图函数ShoppingCart
# @login_required(login_url='/user/login')
# def ShoppingCart(request):
#     # 获取存储在session中的数据，若session中不存在product_info，则返回一个空列表
#     product_list = request.session.get('product_info', [])
#     # 获取get请求参数,若没有请求参数，则返回空值
#     del_product = request.GET.get('product', '')
#     # 判断是否为空，若非空，则删除Session中的商品信息
#     if del_product:
#         # 删除Session中的某个商品数据
#         for i in product_list:
#             if i['product']== del_product:
#                 product_list.remove(i)
#             # 将删除后的数据覆盖原来的Session
#         request.session['product_info'] = product_list
#         return redirect('/shoppingcart')
#     return render(request, 'ShoppingCar.html', context=locals())



# 此处演示视图缓存时使用
# 导入cache_page
from django.views.decorators.cache import cache_page
# 参数cache与全站缓存CACHE_MIDDLEWARE_ALIAS相同
# 参数key_prefix与全站缓存CACHE_MIDDLEWARE_KEY_PREFIX相同
# cache_page(timeout, *, cache=None, key_prefix=None)

# @cache_page(timeout=10, cache='default', key_prefix='MyDjango')
# @login_required(login_url='/user/login')
# def ShoppingCart(request):
#     pass
#     return render(request, 'ShoppingCar.html', locals())



# 此处演示消息提示时使用
# from django.contrib import messages
# from django.template import RequestContext
# def message(request):
#     # 信息添加方法1：info(request, message, extra_tags='', fail_silently=False)
#     messages.info(request, message='提示信息')
#     messages.success(request, message='成功信息')
#     messages.warning(request, message='警告信息')
#     messages.debug(request, message='调试信息')
#     messages.error(request, message='错误信息')
#
#     # 信息添加方法2：add_message(request, level, message, extra_tags='', fail_silently=False)
#     messages.add_message(request, level=messages.INFO, message='提示信息')
#     return render(request, 'message.html', locals(), RequestContext(request))  # 这里必须设置RequestContext(request)，这是Django的上下文处理器，确保信息message对象能在模板引擎中使用
#     # return render(request, 'message.html', context=locals())  # 下面和上面的代码意义一样




# 此处演示分页功能时使用
# 导入分页功能使用到的模块
# from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
#
# # 首页
# def index(request):
#     return render(request, 'index.html', context=locals())
#
# # 购物车
# def ShoppingCart(request):
#     return render(request, 'ShoppingCar.html', context=locals())
#
# # 分页功能
# def PaginationTest(request, page):
#     # 获取数据表index_product表中的全部信息
#     Product_list = Product.objects.all()
#     # 获取分页对象paginator，并设置每页为3个数据
#     paginator = Paginator(object_list=Product_list, per_page=3)
#     try:
#         # 获取当前页面的对象p.page(page)，它其实是一个列表，可以遍历
#         pageInfo = paginator.page(page)
#     except PageNotAnInteger:
#         # 如果参数page不是整型，就返回第一页的数据
#         pageInfo  = paginator.page(1)
#     except EmptyPage:
#         # 若访问的页数大于实际的页数，则返回最后一页的数据
#         pageInfo = paginator.page(paginator.num_pages)
#     return render(request, 'pagination.html', context=locals())


# 演示djandorestframework框架的序列化功能
# 导入djandorestframework框架的序列化功能使用到的模块
# from rest_framework.views import APIView
# from rest_framework.pagination import PageNumberPagination
# from index.serializers import ProductModelSerializer
# from rest_framework.response import Response
# from rest_framework import status
#
#
# # 方法一
# # 基于类的视图
# # 开发者主要通过自定义类来实现视图，自定义类可以选择性的继承父类的APIView，mixins或者generics //dʒɪˈnɛrɪks//
# # APIView类适用于Serializer类和ModelSerializer，而mixins或者generics只适用于ModelSerializer类
# class ProductClassAPIView(APIView):
#     # 当为get请求方式的时候
#     def get(self, request):
#         queryset = Product.objects.all()
#         # 分页查询，需要在settings.py中设置REST_FRAMEWORK属性
#         pg = PageNumberPagination()
#         # paginate_queryset(self, queryset, request, view=None)
#         page_roles = pg.paginate_queryset(queryset=queryset, request=request, view=self)
#         # serializer = ProductModelSerializer(instance=page_roles, many=True)  # 全表查询
#         serializer = ProductModelSerializer(instance=page_roles, many=True)
#         # 返回对象Response由DjangoRestFrameWork实现
#         return Response(serializer.data)
#
#     # 当为post请求方式的时候
#     def post(self, request):
#         # 获取数据
#         serializer = ProductModelSerializer(data=request.data)
#         # 数据验证
#         if serializer.is_valid():
#             # 验证通过，保存到数据库
#             serializer.save()
#             # 返回对象Response由Django Rest FrameWork实现，status用于设置响应状态码
#             return Response(serializer.data, status=status.HTTP_201_CREATED)
#         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
#
#
# # 方法二
# # 普通函数方式生成视图
# # api_view(http_method_names=None)
# from rest_framework.decorators import api_view
#
#
# @api_view(['POST', 'GET'])
# def ProductClass(request, pk):
#     if request.method == "GET":
#         queryset = Product.objects.all().filter(id=pk)
#         serializer = ProductModelSerializer(instance=queryset, many=True)
#         # 返回对象Response由DjangoRestFrameWork实现
#         return Response(serializer.data)
#     elif request.method == "POST":
#         # 获取数据
#         serializer = ProductModelSerializer(data=request.data)
#         # 数据验证
#         if serializer.is_valid():
#             # 验证通过，保存到数据库
#             serializer.save()
#             # 返回对象Response由Django Rest FrameWork实现，status用于设置响应状态码
#             return Response(serializer.data, status=status.HTTP_201_CREATED)
#         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
#
#
# # 方法三
# # 重构ViewSets类，这个过程较为复杂，因此并不建议大家去使用





# 演示基于haystack的站内搜索功能
# # 基于类的视图
# from django.core.paginator import PageNotAnInteger,Paginator, EmptyPage
# from django.conf import settings
# from index.models import *
# from haystack.views import SearchView
#
#
# class MySearchView(SearchView):
#     # 模板文件
#     template = 'search.html'
#
#     # 重写响应方式，如果请求参数q为空，返回模型Product的全部数据，否则根据参数q搜索相关数据
#     def create_response(self):
#         # 请求参数q为空，返回模型Product的全部数据
#         if not self.request.GET.get('q', ''):
#             show_all = True
#             product = Product.objects.all()
#
#             # 分页对象p,由模块Paginator实例化生成。
#             # 某分页对象page2，由对象p使用函数page所生成的对象。
#
#             # 获取分页对象
#             paginator = Paginator(object_list=product, per_page=settings.HAYSTACK_SEARCH_RESULTS_PER_PAGE)
#             # 获取每页对象page2
#             try:
#                 # 如果输入的某一页并不存在，则返回第一页的数据
#                 page = paginator.page(int(self.request.GET.get('page', 1)))
#             except PageNotAnInteger:
#                 # 如果参数page的数据类型不是整型，则返回第一页数据
#                 page = paginator.page(1)
#             except EmptyPage:
#                 # 用户访问的页数大于实际页数，则返回最后一页的数据
#                 page = paginator.page(paginator.num_pages)
#             return render(self.request, self.template, locals())
#
#         else:
#             # 请求参数q不为空，根据参数q搜索相关数据
#             show_all = False
#             qs = super(MySearchView, self).create_response()
#             return qs




# 演示分布式任务系统
from django.http import HttpResponse
from index.tasks import updateData


def IndexCelery(request):
    # 传递参数并执行异步任务
    updateData.delay(2, '170g')
    return HttpResponse("Hello Celery")